package com.tcp.handler;

import com.common.map.NettyChannelMap;
import com.common.message.vo.BaseMessage;
import com.common.message.vo.MessageType;
import io.netty.channel.*;
import io.netty.util.ReferenceCountUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.LoggerFactory;

public class HttpToTcpHandler extends ChannelInboundHandlerAdapter {

    private final static org.slf4j.Logger logger = LoggerFactory.getLogger(HttpToTcpHandler.class);


    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        logger.info("http connect");
        ctx.fireChannelActive();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        logger.info("enter tcp handler read method");
        try {
            if (msg != null && msg instanceof BaseMessage) {
                BaseMessage baseMessage = (BaseMessage) msg;
                if( baseMessage.getType() != null){
                    int type = baseMessage.getType();
                    if (type == MessageType.TCPSERVER_RECEIVE.getCode()) {
                        ReferenceCountUtil.release(msg);
                    } else if (type == MessageType.COMMAND.getCode()) {
                        this.commandProxySend(ctx, msg);
                    } else {
//                    ctx.fireChannelRead(msg);
                    }
                }else{
                    this.receiveTcpClient(ctx, baseMessage);
                }
            }
        } finally {
            ReferenceCountUtil.release(msg);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        ctx.fireExceptionCaught(cause);
        logger.error("[ERROR-TcpHandler]--{}", cause);
        ctx.close();
    }


    private void commandProxySend(ChannelHandlerContext ctx, Object msg) {
        logger.info("enter tcp handler commandProxySend method");
        if (msg != null && msg instanceof BaseMessage) {
            BaseMessage baseMessage = (BaseMessage) msg;
            if (StringUtils.isNoneBlank(baseMessage.getContent()) && baseMessage.getType() != null) {
                int messageType = baseMessage.getType().intValue();
                if (MessageType.COMMAND.getCode() == messageType) {
                    String content = baseMessage.getContent();
                    logger.info("TCP SERVER receive message:{}", content);
                    ChannelFuture future = ctx.writeAndFlush(this.buildBaseMessage("OK"));
                    future.addListener(ChannelFutureListener.CLOSE);
                    this.sendTcpClient(ctx,baseMessage);
                }
            } else {
                this.receiveTcpClient(ctx,baseMessage);
            }
        } else {
            ctx.fireChannelRead(msg);
        }
    }

    private BaseMessage buildBaseMessage(String content) {
        BaseMessage baseMessage = new BaseMessage();
        baseMessage.setContent(content);
        baseMessage.setType(MessageType.TCPSERVER_RECEIVE.getCode());
        return baseMessage;
    }

    private void receiveTcpClient(ChannelHandlerContext ctx, BaseMessage baseMessage) {
        logger.info("receive tcp client message:{}", baseMessage);
        String content = baseMessage.getContent();
        if(StringUtils.isNotBlank(content)){
            String[] strList = content.split(",");
            if (strList != null && strList.length > 0) {
                NettyChannelMap.getInstance().put(strList[1], ctx.channel());
            } else {
                logger.info("content is null");
            }
        }

    }


    private void sendTcpClient(ChannelHandlerContext ctx, BaseMessage baseMessage) {
        String content = baseMessage.getContent();

        String[] strList = content.split(",");
        if (strList != null && strList.length > 0) {
            Channel channel = NettyChannelMap.getInstance().get(strList[1]);
            if(channel != null && channel.isActive()){
                logger.info("send tcp client");
                channel.writeAndFlush(baseMessage);
            }
//            for (int i = 1; i < strList.length; i++) {
//                byte[] bytes = strList[i].getBytes();
//                ctx.channel().write(bytes);
//            }
//            ctx.channel().flush();
        }
    }
}
